package com.google.code.chaotic.ejb;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;

import com.google.code.chaotic.EmFactory;
import com.google.code.chaotic.model.Commuter;
import com.google.code.chaotic.model.CommutingService;

/**
 * Session Bean implementation class MessagingServiceBean
 */
@LocalBean
@Stateless
// (name = "messagingServiceBean")
public class MessagingServiceBean //
		implements MessagingServiceBeanRemote, MessagingServiceBeanLocal {

	private static final Logger logger = Logger //
			.getLogger(AnalysisTimer.class.getName());

	@Inject
	private Context context;

	@Resource(name = "mail/chaosMailSession")
	private Session mailSession;

	//

	@Override
	public void informCommutersInService(String serviceId) {

		EntityManagerFactory emf = EmFactory.get();
		EntityManager em = emf.createEntityManager();
		try {
			if (context == null) { // TODO: Must be removed for roll-out
				context = new InitialContext();
				logger.info("!!!!!!!!!! THE INITIAL CONTEXT ENVIREONMENT: "
						+ context.getEnvironment());
			}

			if (mailSession == null) { // TODO: Must be removed for roll-out
				Properties props = new Properties();
				props.load(AnalysisTimer.class.getResourceAsStream( //
						"/META-INF/chaos-mail-standalone.properties"));
				mailSession = Session.getDefaultInstance(props);
			}
			String //
			sqlStmt1 = "SELECT u.id, " //
					+ "		   hs.cancelling_code " //
					+ " FROM app_user u	" //
					+ " JOIN commuting_habit h ON 	" //
					+ " 	h.f_commuter_id = u.id 	" //
					+ " JOIN habit_in_service hs ON" //
					+ " 	hs.f_habit_id = h.id 	" //	
					+ " WHERE hs.f_service_id = ? 	";

			Connection conn1 = EjbUtils.getConnection(emf);
			PreparedStatement stmt1 = conn1.prepareStatement(sqlStmt1);
			stmt1.setString(1, serviceId);
			ResultSet rs1 = stmt1.executeQuery();

			final Transport transport = mailSession.getTransport("smtps");
			transport.connect("smtp.gmail.com", //
					"the.chaotic.chaos", "123.chaotic");
			ExecutorService execService = Executors.newFixedThreadPool(100);

			while (rs1.next()) {
				Commuter commuter = em
						.find(Commuter.class, rs1.getString("id"));

				StringBuilder recipients = new StringBuilder();
				String email = commuter.getEmail();
				if (!email.matches("commuter\\#.*\\@somenet\\.com")) {
					// TODO: The above "pattern checking" is for
					// testing purpose and must be removed for the roll-out.
					recipients.append(email);
					recipients.append(", ");
				}
				recipients.append("the.chaotic.chaos@gmail.com");

				String firstName = commuter.getFirstName();
				String lastName = commuter.getLastName();

				// TODO: Must be changed for roll-out
				String appHost = InetAddress.getLocalHost().getHostName();
				String appPort = ":8080";
				// String appPort = ":80";
				String cancelingServlet = "/pickupCancelling";

				String cancellingCode = rs1.getString("cancelling_code");

				String subject = "[CHAOS] A Matching Transport Service Found";
				StringBuilder text = new StringBuilder();
				text
						.append("\n")
						.append("Greetings from CHAOS team,\n")
						.append("\n")
						.append("Dear ")
						.append(firstName)
						.append(" ")
						.append(lastName)
						.append(
								", kindly be informed that we have planned a transport service to take you "
										+ "to your registered destination, while sharing the ride with a few other "
										+ "fellows. You can see the route of this service by clicking on the "
										+ "following link:\n")
						//
						.append("\n")
						.append("http://")
						.append(appHost)
						.append(appPort)
						.append("/Chaos.html")
						.append("\n")
						//
						.append(
								"\nIf you are not interested in this particular ride, "
										+ "please click on the following link to remove you from the "
										+ "list of service-takers.\n")
						//
						.append("\n").append("http://").append(appHost).append(
								appPort).append(cancelingServlet).append('?')
						.append("code=").append(cancellingCode);

				text.append("\n");
				text.append("\n");
				final Message msg = new MimeMessage(mailSession);

				msg.setRecipients( //
						Message.RecipientType.TO, //
						InternetAddress.parse(recipients.toString()));
				msg.setSubject(subject);
				msg.setText(text.toString());
				msg.saveChanges();

				execService.execute(new Runnable() {
					@Override
					public void run() {
						try {
							transport.sendMessage(msg, msg.getAllRecipients());

						} catch (MessagingException e) {
							logger.log(Level.SEVERE, e.toString(), e);
						}
					}
				});
			}
			execService.shutdown();

		} catch (AddressException e) {
			logger.log(Level.SEVERE, e.toString(), e);

		} catch (MessagingException e) {
			logger.log(Level.SEVERE, e.toString(), e);

		} catch (FileNotFoundException e) {
			logger.log(Level.SEVERE, e.toString(), e);

		} catch (IOException e) {
			logger.log(Level.SEVERE, e.toString(), e);

		} catch (ClassNotFoundException e) {
			logger.log(Level.SEVERE, e.toString(), e);

		} catch (SQLException e) {
			logger.log(Level.SEVERE, e.toString(), e);

		} catch (NamingException e) {
			logger.log(Level.SEVERE, e.toString(), e);

		} finally {
			em.close();
		}
	}

	public static void main(String[] args) {

		MessagingServiceBean messagingService = new MessagingServiceBean();

		EntityManager em = EmFactory.get().createEntityManager();
		String jqlStmt = "SELECT s FROM CommutingService s ORDER BY s.id";
		TypedQuery<CommutingService> query = em.createQuery( //
				jqlStmt, CommutingService.class);

		query.setMaxResults(2);
		List<CommutingService> services = query.getResultList();
		for (CommutingService service : services) {
			messagingService.informCommutersInService(service.getId());
		}
	}
}
